
/**
  ******************************************************************************
  * Copyright 2021 The Microbee Authors. All Rights Reserved.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  * 
  * @file       xrce_dds_transport.c
  * @author     baiyang
  * @date       2022-3-31
  ******************************************************************************
  */

/*----------------------------------include-----------------------------------*/
#include "xrce_dds_transport.h"

#include <rtthread.h>

#include <common/time/gp_time.h>
#include <serial_manager/gp_serial.h>
/*-----------------------------------macro------------------------------------*/

/*----------------------------------typedef-----------------------------------*/

/*---------------------------------prototype----------------------------------*/

/*----------------------------------variable----------------------------------*/
static rt_device_t xrce_dds_dev;
/*-------------------------------------os-------------------------------------*/

/*----------------------------------function----------------------------------*/
/**
  * @brief       
  * @param[in]     
  * @param[out]  
  * @retval      
  * @note        
  */
bool xrce_dds_transport_have_device()
{
    rt_device_t dev = SerialManager_find_protocol_instance(SerialProtocol_DDS, 0);

    if (dev == NULL) {
        return false;
    }

    return true;
}

/**
  * @brief       
  * @param[in]   transport  
  * @param[out]  
  * @retval      
  * @note        
  */
bool xrce_dds_transport_open(uxrCustomTransport* transport)
{
    xrce_dds_dev = SerialManager_find_protocol_instance(SerialProtocol_DDS, 0);

    if (xrce_dds_dev != NULL && !(xrce_dds_dev->open_flag & RT_DEVICE_OFLAG_OPEN)) {
        rt_err_t err = rt_device_open(xrce_dds_dev, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
        if(err != RT_EOK) {
            rt_kprintf("fail open serial0 device: %ld\n", err);
        }
    } else if (xrce_dds_dev == NULL ) {
        return false;
    }

    return true;
}

/**
  * @brief       
  * @param[in]   transport  
  * @param[out]  
  * @retval      
  * @note        
  */
bool xrce_dds_transport_close(uxrCustomTransport* transport)
{
    if (xrce_dds_dev != NULL) {
        rt_device_close(xrce_dds_dev);
    }

    // Return true if success
    return true;
}

/**
  * @brief       
  * @param[in]   transport  
  * @param[in]   buf  
  * @param[in]   len  
  * @param[in]   errcode  
  * @param[out]  
  * @retval      
  * @note        
  */
size_t xrce_dds_transport_write(uxrCustomTransport* transport, const uint8_t* buf, size_t len, uint8_t* errcode)
{
    *errcode = RT_EOK;

    if (xrce_dds_dev == NULL) {
        *errcode = RT_ERROR;
        return 0;
    }

    size_t bytes_written = rt_device_write(xrce_dds_dev, 0, (void*)buf, (rt_size_t)len);

    if (bytes_written != len) {
        *errcode = RT_EIO;
    }

    return bytes_written;
}

/**
  * @brief       
  * @param[in]   transport  
  * @param[in]   buf  
  * @param[in]   len  
  * @param[in]   timeout  
  * @param[in]   errcode  
  * @param[out]  
  * @retval      
  * @note        
  */
size_t xrce_dds_transport_read(uxrCustomTransport* transport, uint8_t* buf, size_t len, int timeout, uint8_t* errcode)
{
    rt_size_t bytes_read = 0;
    uint32_t time_start_ms = time_millis();

    if (xrce_dds_dev == NULL) {
        *errcode = RT_ERROR;
        return 0;
    }

    do {
        bytes_read += rt_device_read(xrce_dds_dev, 0, (void*)&buf[bytes_read], (rt_size_t)(len - bytes_read));

        if (timeout > 0) {
            rt_thread_mdelay(1);
        }
    } while (bytes_read < len && (time_millis() - time_start_ms < timeout));

    // console_printf("read serial platform: %d %d\n", len, bytes_read);

    return bytes_read;
}

/*------------------------------------test------------------------------------*/

